//
//  DeviceModel.swift
//  
//
//  Created by tank on 2021/11/17.
//

import Foundation
import UIKit

public struct DeviceModel: Codable {
    enum CodingKeys: CodingKey {
        case id
        case date
        case systemInfo
        case appVersion
        case userAgreementVersion
        case privacyAgreementVersion
        case guideVersion
    }
    
    
    public let id: String
    
    public let date: Date
    
    /// 用户协议
    public var userAgreementVersion: String?
    
    /// 隐私协议
    public var privacyAgreementVersion: String?
    
    /// 用户引导版本
    public var guideVersion: String?
    
    public var systemInfo: String = {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else {
                return identifier
            }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        
        return "\(UIDevice.current.name);\(UIDevice.current.systemName);\(UIDevice.current.systemVersion);\(UIDevice.current.model);\(identifier)"
    }()
    
    public var appVersion: String = {
        return Bundle.main.ex.appVersion
    }()
    
    
    init(id: String, date: Date) {
        self.id = id
        self.date = date
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(String.self, forKey: .id)
        self.date = try container.decode(Date.self, forKey: .date)
        self.userAgreementVersion = try container.decodeIfPresent(String.self, forKey: .userAgreementVersion)
        self.privacyAgreementVersion = try container.decodeIfPresent(String.self, forKey: .privacyAgreementVersion)
        self.guideVersion = try container.decodeIfPresent(String.self, forKey: .guideVersion)
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(date, forKey: .date)
        try container.encodeIfPresent(userAgreementVersion, forKey: .userAgreementVersion)
        try container.encodeIfPresent(privacyAgreementVersion, forKey: .privacyAgreementVersion)
        try container.encodeIfPresent(guideVersion, forKey: .guideVersion)
        try container.encode(systemInfo, forKey: .systemInfo)
        try container.encode(appVersion, forKey: .appVersion)
    }
}
